#include <iostream>

// class JustAClass {
// private:
//     int* a;
// public:
//     JustAClass() {
//         std::cout << "Constructor" << std::endl;
//         //throw std::invalid_argument("=========");
//         a = new int(10);
//     }

//     JustAClass(const JustAClass& o) {
//         std::cout << "Copy Constructor" << std::endl;
//         a = new int(*o.a);
//     }

//     JustAClass(JustAClass&& o) {
//         a = o.a;
//         o.a = nullptr;
//     }

//     ~JustAClass() {
//         std::cout << "Destructor" << std::endl;
//         if (a != nullptr)
//             delete a;
//     }

// public:
//     JustAClass& operator=(const JustAClass& o) {
//         std::cout << "Copy Assign" << std::endl;
//         if (this == &o)
//             return *this;
        
//         delete a;
//         throw std::invalid_argument("=========");
//         a = new int(*o.a);
//     }

//     JustAClass& operator=(JustAClass&& o) {
//         if (this == &o)
//             return *this;
        
//         a = o.a;
//         o.a = nullptr;
//     }
// };


class JustAClass {
private:
    int a;
    int b;
    int* c;

private:
    friend void swap(JustAClass&, JustAClass&);

public:
    JustAClass(int a = 0, int b = 0, int ic = 0) 
        : a(a), b(b), c(ic == 0 ? nullptr : new int(ic))
    {
    }

    JustAClass(const JustAClass& o) 
        : a(o.a), b(o.b), c(new int(0))
    {
        std::copy(o.c, o.c + 1, c);
    }

    JustAClass(JustAClass&& o) noexcept
        : JustAClass()
    {
        swap(o, *this);
    }

    ~JustAClass()
    {
        if (c != nullptr)
            delete c;
    }

public:
    JustAClass& operator=(JustAClass o)
    {
        swap(o, *this);
        return *this;
    }
};

void swap(JustAClass& a, JustAClass& b)
{
    using std::swap;
    swap(a.a, b.a);
    swap(a.b, b.b);
    swap(a.c, b.c);
}

int main() {
    // JustAClass a;
    // JustAClass b;

    // try {
    //     //JustAClass a;

    //     a = b;
    // }
    // catch(...) {
    //     std::cout << "error" << std::endl;
    // }

    JustAClass a(1, 2, 3);
    JustAClass b(3, 2, 1);
    JustAClass c(4, 5, 6);

    a = b;

    c = std::move(a);

    return 0;
}